package com.qf.aop.impl;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.qf.aop.annocation.LoginUser;
import com.qf.consants.RabbitMQConstants;
import com.qf.entity.User;
import com.qf.utils.JWTUitls;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Component
@Aspect
public class LoginUserAOPImpl {

//    @Autowired
//    private HttpServletRequest request;

    // Aspect
    @Around("@annotation(loginUser)")
    public Object parseToken(ProceedingJoinPoint point, LoginUser loginUser) throws Throwable {

        // 1.先获取HttpServeltRequest对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        // 2.从req对象中获取后去请求头
        String token = request.getHeader(RabbitMQConstants.SSO_LGOIN_TOKEN_NAME);

        // 如果请求头中没有获取到token，尝试从查询参数中获取
        if(StringUtils.isEmpty(token)){
            token = request.getParameter(RabbitMQConstants.SSO_LGOIN_TOKEN_NAME);
        }

        // 3.判断token是否为空
        User user = null;
        if (!StringUtils.isEmpty(token)) {

            // 4.校验token
            DecodedJWT decodedJWT = JWTUitls.checkToken(token); // 如果校验失败会抛出异常，不用管，因为有全局异常存在

            // 5.从token中获取userid
            String userId = JWTUitls.getWithClaim(decodedJWT, "id");
            String username = JWTUitls.getWithClaim(decodedJWT, "username");

            // 6.封装成一个User对象
            user = new User();
            user.setUsername(username);
            user.setId(Integer.parseInt(userId));
        }

        // 7.获取当前请求传递的参数
        Object[] args = point.getArgs(); // 获取Controller方法上的参数

        // 8.从args中找到user对象的
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof User) {
                args[i] = user; // 把args中的user对象替换我们自己封装的
                break;
            }
        }

        // 9.调用目标方发
        return point.proceed(args); // 因为我们替换了目标方法的参数，所以这里一定要传递下去
     }

}
